package tp.pr5.items;

import java.util.ArrayList;
import tp.pr5.Main;
import tp.pr5.Observable;

public class ItemContainer extends Observable<InventoryObserver> {	
	//Item[] inventory;
	int count;
	ArrayList<Item> inventory;
	/**
	 * Creates the empty container
	 */
	public ItemContainer() {	
		//this.inventory = new Item[100];
		this.inventory = new ArrayList<Item>();
		this.count = 0;
	}
	
	public int getItemCount(){
		if(!this.inventory.isEmpty()){
			return this.inventory.size();
		}else{
			return 0;
		}
	}
	
	/**
	 * Funcion para ver si un item esta en el array
	 */
	public boolean findItem(Item item){
		boolean found = false;
		int i = 0;
		while(i < this.inventory.size() && !found){
			if(this.inventory.get(i) != null){				
				if(this.inventory.get(i).getId().equalsIgnoreCase(item.getId())){
					found = true;
				}
			}
			i++;
		}
		return found;
	}
	/**
	 * Funcion para ver si un item esta en el array (por id)
	 */
	public boolean findItem(String itemId){
		boolean found = false;
		int i = 0;
		while(i < this.inventory.size() && !found){
			if(this.inventory.get(i) != null){
				if(this.inventory.get(i).getId().equalsIgnoreCase(itemId)){
					found = true;
				}
			}
			i++;
		}
		return found;
	}	
	/**
	 * Funcion para buscar posicion de insercion
	 */
	private int findInsertPosition(Item item){
		if(!findItem(item)){//por si acaso, no debería ocurrir nunca
			for(int i=0; i< this.inventory.size() ; i++){ 
				if (this.inventory.get(i) != null){
					Item it = this.inventory.get(i);
					if(it.getId().compareToIgnoreCase(item.getId())>0){						
						return i;						
					}else{
						//sigue buscando
					}
				}else{
					return i;
				}			
			}
			return 0;
		}
		return -1; //en caso de fallo catastrofico 
	}
	/**
	 * Returns the number of items contained 
	 * @return
	 */
	public int	numberOfItems(){		
		return this.inventory.size();	
	}

	/**
	 * Add an item to the container. The operation can fail, returning false
	 * @param item
	 * @return
	 */
	public boolean addItem(Item item){
		if(!findItem(item)){//si el item no está ya
			if(this.inventory.isEmpty()){
				this.inventory.add(item);
			}else{						
				int pos = findInsertPosition(item);			
				this.inventory.add(pos,item);
			}	
			return true;
		}else{
			return false;
		}	
	} 
	/**
	 * Returns the item from the container according to the item name
	 * @param id
	 * @return
	 */
	public Item getItem(String id){
		if(findItem(id)){
			for(int i=0;i<this.inventory.size();i++){
				if(this.inventory.get(i) != null){
					if(this.inventory.get(i).getId().equalsIgnoreCase(id)){
						return this.inventory.get(i);
					}				
					
				}
			}
		}
		return null;
	} 
	/**
	 * Returns and deletes an item from the inventory. This operation can fail, returning null
	 * @param id
	 * @return
	 */
	public Item pickItem(String id) {
		if(findItem(id)){
			for(int i=0;i<this.inventory.size(); i++){
				if (this.inventory.get(i) != null){
					Item it = this.inventory.get(i);
					if(it.getId().equalsIgnoreCase(id)){						
						removeItem(i);						
						return it;
					}
				}			
			}
		}
		return null;
	}
	/**
	 * Removes an item from the array in the given position
	 */
	private void removeItem(int i){
		this.inventory.remove(i);		
	}
	/**
	 * Generates a String with information about the items contained in the container. Note that the items must appear sorted but the item name.
	 */
	public String listItems(){
		//compactAndSortArray();
		
		String ret = "";
		for(int i=0;i< this.inventory.size();i++){
			if(this.inventory.get(i) != null){
				String endl = "";
				if(i != this.inventory.size()-1) endl = Main.LINE_SEPARATOR;
				ret += "   "+this.inventory.get(i).getId()+endl;
			}						
		}
		return ret;
	}
	public String toString(){		
		return listItems();	
	}
	//repetida
	public boolean containsItem(String id) {
		return this.findItem(id);
	}
	/**
	 * Returns the inventory as ArrayList
	 */
	public ArrayList<Item> getItemInventory(){
		return this.inventory;
	}
	/**
	 * 
	 */
	public void 	requestScanCollection() {
		String message;
		if(this.numberOfItems() <= 0){//si el inventario estÃ¡ vacÃ­o
			message = "My inventory is empty";
							
		}else{			
			message = "I am carrying the following items"+Main.LINE_SEPARATOR+this.toString();
			
		}
		/*
		 * Lanza a todos los observers el scan del inventario
		 */
		for(InventoryObserver io: this.lista){					
			io.inventoryScanned(message);
		}
	}
	/**
	 * PRECOND: The item exists
	 * Requests a scan from the instruction
	 * @param id
	 */
	public void 	requestScanItem(String id){
		String message = "";
		if(id==null || id==""){//si no hay segundo parametro
			requestScanCollection();
		}else{//si tiene segundo parÃ¡metro
			if (this.findItem(id)){//si encuentra el item pedido
				Item it = this.getItem(id); 
				message = it.toString();
				
			}else{//si no encuentra el item pedido			
				
				message = "I have not such object";
			
			}
		}
		/*
		 * Lanza a todos los observers el scan del item
		 */
		for(InventoryObserver io: this.lista){					
			io.itemScanned(message);
		}
	}
	/**
	 * Method called by the OperateInstruction when an item stored in the collection is successfully used.
	 * @param item
	 */
	public void 	useItem(Item item){
		/*
		 * si ya no puede ser usado, es que está vacío
		 */
		
		if(!item.canBeUsed()){
			for(InventoryObserver io: this.lista){
				io.itemEmpty(item.getId());
			}			
		}	
	}
	/**
	 * emits notification that the inventory has changed
	 */
	public void emitInventoryChanged() {
		for(InventoryObserver io : this.lista){
			io.inventoryChange(this.inventory);
		}		
	}
	
	

}
